# -*- coding: utf-8 -*-
# @File  : thread信号量.py
# @Author: zbh
# @Date  : 2025/2/27_15:57

'''
threading.Semaphore()创建信号量对象，然后在需要同步的代码块中使用acquire()和release()方法来获取和释放信号量。
acquire()方法会阻塞当前线程，直到获取到信号量为止。release()方法会释放信号量。
信号量，在同一时刻，只有n个线程可以获取到信号量，其他线程需要等待信号量被释放后才能获取到信号量。
也就是说同一时刻只允许n个线程访问共享数据；

互斥锁同一时刻只允许一个线程访问共享数据，而信号量在同一时刻允许一定数量的线程访问共享数据。
比如柜台有5个窗口，允许同时有5个人办理业务，后面的人只能等待，5人中有人办理完业务，等待的人才能去办理
'''

import threading
import time
import random

current_user = [] # 各线程之间可访问同一内存块，即可访问同一全局变量

def work_func(semaphore,name):
    print(f"当前激活的线程数量：{threading.active_count()}","\n") # 打印当前激活的线程数量（含主线程）
    semaphore.acquire() # 获取信号量
    current_user.append(threading.currentThread().name) # 将当前线程名添加到列表中
    print(f"当前办理业务的顾客有：{current_user},顾客{name}正在办理业务")
    time.sleep(random.randint(1,5)) # 模拟办理业务的时间
    current_user.remove(threading.currentThread().name) # 将当前线程名从列表中移除
    # print(f"当前办理业务的顾客有：{current_user},顾客{name}已经办理完业务")
    semaphore.release() # 释放信号量

def main():
    thread_list = []
    semaphore = threading.BoundedSemaphore(5) # 创建信号量对象, 最多允许5个线程同时访问共享数据
    for i in range(18):
        t = threading.Thread(target=work_func,args=(semaphore,i+1)) # 创建线程对象, target是函数名，args是函数的参数
        thread_list.append(t) # 将线程对象添加到列表中

    for t in thread_list:
        t.start() # 启动线程, 线程的入口点，线程要执行的内容在这里
        print(t.name,"开始运行")
    for t in thread_list:
        t.join() # 等待线程结束,确保主线程会等待所有子线程执行完毕后再继续执行后续代码

if __name__ =="__main__":  # 程序入口
    main()





